﻿using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Qianke.Core.Common.Interface;
using System.Diagnostics;
using System.Reflection;
using Volo.Abp.Application;
using Volo.Abp.Domain;
using Volo.Abp.Domain.Entities.Caching;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;

namespace Qianke.Core.Saas.Application
{
    [DependsOn(
        typeof(AbpDddApplicationModule),
        typeof(AbpDddDomainModule),
        typeof(AbpEntityFrameworkCoreModule)
        )]
    public class SaasApplicationModule : AbpModule
    {


        public void RegisterEntityCachesForIHasName(IServiceCollection services)
        {
            // 获取当前程序的所有程序集
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            // 查找实现了 IHasName 接口的所有类型
            var typesWithIHasName = assemblies
                .SelectMany(assembly => assembly.GetTypes())
                .Where(type => typeof(IHasName).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
                .ToList();

            // 获取泛型方法定义
            var genericAddEntityCacheMethod = typeof(EntityCacheServiceCollectionExtensions)
                .GetMethods(BindingFlags.Static | BindingFlags.Public)
                .Where(u => u.Name == nameof(EntityCacheServiceCollectionExtensions.AddEntityCache))
                .Where(u => u.IsGenericMethod)
                .Where(u => u.GetGenericArguments().Length == 2)
                .Where(u => u.GetParameters().Length == 2)
                .FirstOrDefault();

            // 遍历这些类型并注册到 EntityCache
            foreach (var entityType in typesWithIHasName)
            {
                // 默认使用实体的主键类型为 TKey
                Type keyType = GetPrimaryKeyType(entityType);
                Trace.WriteLine($"注册实体 {entityType.FullName} 的缓存，主键类型为 {keyType.FullName}。");
                if (keyType != null)
                {
                    var genericArguments = genericAddEntityCacheMethod.MakeGenericMethod(entityType, keyType);
                    // 调用泛型方法
                    genericArguments.Invoke(null, new object[] { services, (DistributedCacheEntryOptions)null });
                }
                else
                {
                    throw new InvalidOperationException($"无法确定实体 {entityType.FullName} 的主键类型。");
                }
            }
        }

        private static Type GetPrimaryKeyType(Type entityType)
        {
            // 假设实体类有一个属性标记为 [Key] 或者是默认的 Id 属性
            var keyProperty = entityType.GetProperties()
                .FirstOrDefault(p => p.Name == "Id" || p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.KeyAttribute), false).Length > 0);

            if (keyProperty != null)
            {
                return keyProperty.PropertyType;
            }

            return null;
        }
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            RegisterEntityCachesForIHasName(context.Services);
        }
    }
}
